#include <sinsy/sinsy.h>
#include <sndfile.h>
#include "boost/filesystem.hpp"
#include "sekai/UTAUSynth.h"

using namespace std;

void usage() {
  fprintf(stderr, "usage: utau_synth voicedir input.xml output.wav\n");
}

int main(int argc, char **argv) {
  if (argc != 4) {
    usage();
    return -1;
  }

  std::string voice = argv[1];
  std::string xml = argv[2];
  std::string wav = argv[3];

  sinsy::Sinsy sinsy;

  std::string oto_ini = voice + "/oto.ini";
  std::string oto_json = voice + "/oto.json";

  if (!boost::filesystem::exists(oto_ini)) {
    std::cout << "[ERROR] : " << oto_ini << " does not exist" << std::endl;
    return -1;
  }
  if (!boost::filesystem::exists(oto_json)) {
    std::cout << "[ERROR] : " << oto_json << " does not exist" << std::endl;
    return -1;
  }

  if (!sinsy.loadUtauDB(voice + "/oto.ini")) {
    std::cout << "[ERROR] failed to load utaudb : " << voice << std::endl;
    return -1;
  }

#if 0
  //first check oto.ini and oto.json exist
  //config for synth backend
  Json::Value voiceconfig;
  if (!read_json(voice + "/oto.json",voiceconfig)) {
    std::cout << "[ERROR] failed to load utaudb : " << voice << std::endl;
    return -1;
  }
#endif

  if (!sinsy.loadScoreFromMusicXML(xml)) {
    std::cout << "[ERROR] failed to load score from MusicXML file : " << xml
              << std::endl;
    return -1;
  }

  UTAUSynth synth(voice);  // voiceconfig
  sinsy.synthesize(&synth);
  synth.fix();

  SF_INFO info = {0};

  info.samplerate = synth.samplerate();
  info.channels = 1;
  info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;

  SNDFILE *sf = sf_open(wav.c_str(), SFM_WRITE, &info);

  while (1) {
    const int size = 1024;
    int fill = size * 4;

    float buffer_out[size];
    if (synth.readData(buffer_out, size, fill) == false) break;
    sf_write_float(sf, buffer_out, size);
  }

  sf_close(sf);

  return 0;
}
